<template>
  <div class="digital-human">
    <!-- 图片元素 -->
    <div class="image-container">
      <img :src="currentFrame" class="frame-image" alt=""/>
    </div>

    <!-- 输入框和提交按钮 -->
    <div class="input-section">
      <input v-model="userInput" type="text" placeholder="请输入内容" class="input-box"/>
      <button @click="handleSubmit" class="submit-button" :disabled="isSubmitting">提交</button>
    </div>

    <div ref="linkSection" class="link-section" v-show="isLinkVisible">
      <div v-for="(url, index) in urls" :key="index">
        链接地址: <a :href="url" class="link">{{ url }}</a>
      </div>
    </div>
    <div class="error-message" v-if="errorMessage">{{ errorMessage }}</div>
    <div class="error-message" v-if="errorMessage2">{{ errorMessage2 }}</div>
  </div>
</template>

<script>
import { onMounted, ref } from 'vue';
import axios from 'axios';

export default {
  setup() {
    const loadedImages = ref([]);
    const userInput = ref('');
    const isSubmitting = ref(false);
    const errorMessage = ref('');
    const errorMessage2 = ref('');
    const isLinkVisible = ref(false);
    const urls = ref([]);
    const currentFrame = ref('');
    const frameIndex = ref(1);
    let frameInterval = null;

    const totalFrames = 30;
    const framePathTemplate = "https://assets-service.obs.cn-south-1.myhuaweicloud.com/ImageHuman/1717658488515_3480_";

    const preloadImages = async () => {
      isSubmitting.value = true;
      errorMessage.value = '我正在初始化图片;';
      const imagePromises = [];
      for (let i = 1; i <= totalFrames; i++) {
        const frameNumber = String(i).padStart(6, '0');
        const imageUrl = `${framePathTemplate}${frameNumber}.png?x-image-process=image/resize,p_100`;
        imagePromises.push(
            fetch(imageUrl)
                .then(response => {
                  if (!response.ok) throw new Error('网络响应不正常');
                  return response.blob();
                })
                .then(blob => {
                  const url = URL.createObjectURL(blob);
                  loadedImages.value[i] = url;
                })
                .catch(error => {
                  console.error('预加载失败:', error);
                })
        );
      }
      await Promise.all(imagePromises);
      isSubmitting.value = false;
      errorMessage.value = '我初始化图片完毕;';
    };

    const updateFrame = () => {
      if (frameIndex.value > totalFrames) {
        frameIndex.value = 1;
      }
      currentFrame.value = loadedImages.value[frameIndex.value];
      frameIndex.value++;
    };

    const startAnimation = () => {
      if (!frameInterval) {
        frameInterval = setInterval(updateFrame, 100);
      }
    };

    const stopAnimation = () => {
      if (frameInterval) {
        clearInterval(frameInterval);
        frameInterval = null;
      } else {
        errorMessage.value = '我停止帧动画没有成功';
      }
    };

    const handleSubmit = async () => {
      if (userInput.value) {
        try {
          isSubmitting.value = true;
          errorMessage.value = '';

          await testToAudio(userInput.value);
        } catch (error) {
          console.error('请求出错:', error);
          errorMessage.value = '请求失败，请稍后重试。';
        } finally {
          userInput.value = '';
          isSubmitting.value = false;
        }
      }
    };

    // 使用 Web Audio API 播放音频
    const playAudioWithWebAudio = async (base64Audio) => {
      const audioContext = new (window.AudioContext || window.webkitAudioContext)();
      const audioData = atob(base64Audio);
      const buffer = new Uint8Array(audioData.length);

      for (let i = 0; i < audioData.length; i++) {
        buffer[i] = audioData.charCodeAt(i);
      }

      try {
        const decodedData = await audioContext.decodeAudioData(buffer.buffer);
        const source = audioContext.createBufferSource();
        source.buffer = decodedData;
        source.connect(audioContext.destination);
        source.start(0);
        startAnimation();

        source.onended = () => {
          errorMessage.value = '我执行了处理音频播放完毕的逻辑';
          stopAnimation();
          imageIni();
        };
      } catch (error) {
        console.error("音频解码错误:", error);
        stopAnimation();
      }
    };

    const testToAudio = async (message) => {
      const audioResponse = await axios.post('https://test-wd-api.iwanshang.cloud/kma/gpt/audio/text2Audio', {
        text: message,
      });

      console.log('语音数据:', audioResponse.data);
      if (audioResponse.data.code === 200 && audioResponse.data.audio) {
        const base64Audio = audioResponse.data.audio;
        await playAudioWithWebAudio(base64Audio); // 使用 Web Audio API 播放音频
      } else {
        console.error('未能获取到有效的音频数据');
      }
    };

    onMounted(async () => {
      await preloadImages();
      await imageIni();
    });

    const imageIni = () => {
      frameIndex.value = 1;
      const frameNumber = String(frameIndex.value).padStart(6, '0');
      currentFrame.value = `${framePathTemplate}${frameNumber}.png`;
    };

    return {
      userInput,
      isSubmitting,
      errorMessage,
      errorMessage2,
      currentFrame,
      isLinkVisible,
      urls,
      handleSubmit,
      imageIni,
    };
  },
};
</script>

<style scoped>
.error-message {
  color: red;
  font-size: 1rem;
  margin-top: 10px;
}

.digital-human {
  position: relative;
  width: 90vw;
  max-width: 360px;
  height: 60vh;
  max-height: 640px;
  background: transparent;
  transition: transform 0.3s ease-in-out, box-shadow 0.3s ease-in-out;
}

.image-container {
  background-color: transparent;
}

.frame-image {
  background-color: transparent;
}

.input-box {
  padding: 10px;
  margin-bottom: 10px;
  width: 100%;
  max-width: 300px;
  border-radius: 5px;
  border: 1px solid #ccc;
}

.submit-button {
  padding: 10px 20px;
  background-color: #007bff;
  color: white;
  border: none;
  border-radius: 5px;
  cursor: pointer;
}

.submit-button:hover {
  background-color: #0056b3;
}

.link-section {
  margin-top: 20px;
}

.link {
  color: #3498db;
  font-size: 1.2rem;
  text-decoration: none;
  font-weight: bold;
}

.link:hover {
  color: #2980b9;
  text-decoration: underline;
}
</style>
